package org.yzhzc.friend.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.yzhzc.common.core.constants.Constants;
import org.yzhzc.common.core.enums.ResultCode;
import org.yzhzc.common.core.utils.ThreadLocalUtil;
import org.yzhzc.common.security.exception.ServiceException;
import org.yzhzc.friend.domain.user.vo.UserVO;
import org.yzhzc.friend.manager.UserCacheManager;

import java.util.Objects;

/**
 * 用户状态检查切面。
 * 该切面用于在方法执行前检查用户状态，确保用户存在且未被禁用。
 * 适用于标注了 {@link CheckUserStatus} 注解的方法。
 *
 * 主要逻辑：
 * 1. 从线程本地变量中获取当前用户的 ID。
 * 2. 根据用户 ID 从缓存中获取用户信息。
 * 3. 检查用户是否存在，如果不存在则抛出异常。
 * 4. 检查用户是否被禁用，如果被禁用则抛出异常。
 *
 * 依赖：
 * - {@link UserCacheManager}：用于从缓存中获取用户信息。
 * - {@link ThreadLocalUtil}：用于从线程本地变量中获取用户 ID。
 * - {@link ServiceException}：用于抛出业务异常。
 * - {@link Constants}：定义了常量值，如用户状态。
 */
@Aspect // 标识该类为切面类
@Component // 将切面类注册为 Spring 组件
public class UserStatusCheckAspect {

    @Autowired
    private UserCacheManager userCacheManager; // 用户缓存管理器，用于获取用户信息

    /**
     * 在标注了 {@link CheckUserStatus} 注解的方法执行前执行。
     *
     * @param point 切点对象，包含方法执行的上下文信息
     * @throws ServiceException 如果用户不存在或用户被禁用，则抛出异常
     */
    @Before(value = "@annotation(org.yzhzc.friend.aspect.CheckUserStatus)")
    public void before(JoinPoint point) {
        // 从线程本地变量中获取当前用户的 ID
        Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);

        // 根据用户 ID 从缓存中获取用户信息
        UserVO user = userCacheManager.getUserById(userId);

        // 检查用户是否存在
        if (user == null) {
            throw new ServiceException(ResultCode.FAILED_USER_NOT_EXISTS);
        }

        // 检查用户是否被禁用
        if (Objects.equals(user.getStatus(), Constants.FALSE)) {
            throw new ServiceException(ResultCode.FAILED_USER_BANNED);
        }
    }
}